package com.lagou.edu.context;

import com.lagou.edu.context.fatory.BeanFacotory;
import com.lagou.edu.context.stereotype.AutoWired;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author zhaozuowen
 * @Description 基于注解功能的spring ioc容器
 * @Date 2020-01-11 11:29
 **/

public class AnnotationConfigApplicationContext implements BeanFacotory {

    public Map<String,Object> singtonMap=new ConcurrentHashMap<>();

    //类路径bean定义扫描器
    private ClassPathBeanDefinitionScanner scanner ;

    public AnnotationConfigApplicationContext(String... basePackages) throws InstantiationException, IllegalAccessException {
        this();
        scan(basePackages);
    }

    public AnnotationConfigApplicationContext() {
        scanner=new ClassPathBeanDefinitionScanner(this);

    }
    private void scan(String... basePackages) throws IllegalAccessException, InstantiationException {
        this.scanner.scan(basePackages);
    }

    public  Object getBean(String beanName){
        return singtonMap.get(beanName);
    }

    public  void populateProperties() throws IllegalAccessException {
        Set<Map.Entry<String, Object>> entries = singtonMap.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            Object object = entry.getValue();
            Field[] declaredFields = object.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                if(annotation!=null){
                    //获取注入属性的类型，然后从
                    Class<?> type = declaredField.getType();
                    declaredField.setAccessible(true);
                    declaredField.set(object,getBean(type));
                }

            }



        }

    }


    public Object getBean(Class aClass){
        Set<Map.Entry<String, Object>> entries = singtonMap.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            Object value = entry.getValue();
            if(aClass.isAssignableFrom(value.getClass())||aClass.equals(value.getClass())){
                return value;
            }
        }
        return null;
    }

    public void register(String beanName,Object instance) {
        singtonMap.put(beanName, instance);
    }
}
